<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"
    />
    <title>Document</title>
    <style>
      .draggable {
        width: 100px;
        height: 100px;
        position: absolute;
        background-color: lightcoral;
        cursor: move;
      }
    </style>
  </head>
  <body>
    <div class="draggable" style="left: 50px; top: 50px"></div>
    <div class="draggable" style="left: 50px; top: 200px"></div>
    <div class="draggable" style="left: 50px; top: 350px"></div>
    <script>
      const draggables = document.querySelectorAll(".draggable");
      let currentDragging=null;
      document.addEventListener("mousedown", (event) => {
        const { target } = event;
        if (target.classList.contains("draggable")) {
          //设置当前正在拖动的元素为draggable
          currentDragging = target;
          //把按下鼠标左键的时候，距离元素左则的偏移量记录元素的自定义属性集合对象上
          currentDragging.dataset.offsetX = event.offsetX;
          currentDragging.dataset.offsetY = event.offsetY;
        }
      });
      document.addEventListener("mousemove", (event) => {
        //如果当前没有要拖动的元素就直接返回了
        if (!currentDragging) return;
        //如果当前有正在拖动的元素，就可以重新计算元素的位置了 x y
        const newLeft = event.clientX - currentDragging.dataset.offsetX;
        const newTop = event.clientY - currentDragging.dataset.offsetY;
        //不能让当前的元素拖动到别的元素上
        //循环所有的可拖动的元素，判断当前正在拖动的元素和它们是否有交叉，如果有则不能拖动指入位置
        for (const draggable of draggables) {
          //如果当前正在拖动的元素和draggable指向相同的元素，继续循环下一个元素
          if (draggable === currentDragging) continue;
          const draggableRect = draggable.getBoundingClientRect();
          if (
            newLeft < draggableRect.right &&
            newLeft + currentDragging.offsetWidth > draggableRect.left &&
            newTop < draggableRect.bottom &&
            newTop + currentDragging.offsetHeight > draggableRect.top
          ) {
            return;
          }
        }
        currentDragging.style.left = newLeft + "px";
        currentDragging.style.top = newTop + "px";
      });
      document.addEventListener("mouseup", (event) => {
        currentDragging = null;
      });
    </script>
  </body>
</html>
